package com.xuzimian.globaldemo.spring.springmvc.controller;

import java.net.URI;
import java.util.Date;
import java.util.List;

import com.google.common.collect.Lists;
import com.xuzimian.globaldemo.spring.springmvc.exception.Error;
import com.xuzimian.globaldemo.spring.springmvc.exception.SpittleNotFoundException;
import com.xuzimian.globaldemo.spring.springmvc.model.Spittle;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;


@RestController
@RequestMapping("/spittles")
public class RestApiController {

    private static final String MAX_LONG_AS_STRING = "9223372036854775807";





    /**
     * produces属性值表明这个方法只处理客户端预期输出为json的请求，
     * 也就是Accept头部信息包含"application/json"的请求
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET, produces = "application/json")
    public Spittle spittleById(@PathVariable Long id) {
        if (id.equals(1L)) {
            return getSpittle(id);
        } else {
            throw new SpittleNotFoundException(id);
        }
    }


    @RequestMapping(method = RequestMethod.GET, produces = "application/json")
    public List<Spittle> spittles(
            @RequestParam(value = "max", defaultValue = MAX_LONG_AS_STRING) long max,
            @RequestParam(value = "count", defaultValue = "20") int count) {
        return getSpittles(max, count);
    }

    /**
     * 1.consumes属性值表明限定了该方法请接受请求的头部信息Content-Type为a"application/json"
     * 也就是客户端发送的数据是json表述形式的，它会要求SpringMvc只处理"/spittles"的post请求，
     * 且Content-Type头部是"application/json"。
     * 2.Spring提供了UriComponentsBuilder，它是一个构建类，通过逐步指定url中的个组成部分，能够
     * 使用它来构建UriComponents实例，适合设置给Location头部信息的URI,在处理器中所得到的UriComponentsBuilder
     * 会预先配置已知的信息如host,端口，以及servlet内容。
     *
     * @param spittle
     * @param ucb
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, consumes = "application/json")
    @ResponseStatus(HttpStatus.CREATED)
    public ResponseEntity<Spittle> saveSpittle(@RequestBody Spittle spittle, UriComponentsBuilder ucb) {
        Spittle saved = spittle;

        HttpHeaders headers = new HttpHeaders();
        URI locationUri = ucb.path("/spittles/")
                .path(String.valueOf(saved.getId()))
                .build()
                .toUri();
        headers.setLocation(locationUri);

        ResponseEntity<Spittle> responseEntity = new ResponseEntity<Spittle>(saved, headers, HttpStatus.CREATED);
        return responseEntity;
    }

    /**
     * 注解能够用到控制器方法中，用来处理特定的异常。这里表明如果RestApiController控制器的任意方法抛出
     * SpittleNotFoundException异常，就会调用spittleNotFound()方法来处理异常并返回。
     *
     * @param e
     * @return
     */
    @ExceptionHandler(SpittleNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public @ResponseBody
    Error spittleNotFound(SpittleNotFoundException e) {
        long spittleId = e.getSpittleId();
        return new Error(4, "Spittle [" + spittleId + "] not found");
    }

    private List<Spittle> getSpittles(long max, int count) {
        List<Spittle> spittles = Lists.newArrayList();
        spittles.add(getSpittle(1));
        spittles.add(getSpittle(2));
        spittles.add(getSpittle(3));
        return spittles;
    }

    private Spittle getSpittle(long id) {
        return new Spittle(id, "xzm" + id, new Date(), 1.65, 13.2);
    }
}